package com.br.aiops.alert;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.br.aiops.alert.config.Receiver;
import com.br.aiops.alert.config.ReceiverCache;
import com.br.aiops.alert.message.AlertMessage;
import com.br.aiops.alert.message.LogAlertMessage;
import com.br.aiops.counter.AlertLogCounter;
import lombok.Builder;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Component
public class AlertData {

    private static final Logger LOGGER = LoggerFactory.getLogger(AlertData.class);
    public static final String DEFAULT_MAIL_TYPE = "1";
    public static final String DEFAULT_MSG_TYPE = "1";
    public static final String WARN = "WARN";
    public static final String ERROR = "ERROR";
    public static final String FATAL = "FATAL";
    public static final String MAILS = "mails";
    public static final String PHONES = "phones";
    public static final String CAS_NAMES = "casNames";


    @Value("${env.group-id}")
    private String group;
    @Value("${alert.app-name}")
    private String appName;
    @Value("${alert.app-secret-key}")
    private String appSecretKey;
    @Value("${alert.send-code.warn}")
    private String sendCodeWarn;
    @Value("${alert.send-code.error}")
    private String sendCodeError;
    @Value("${alert.send-code.fatal}")
    private String sendCodeFatal;

    @Autowired
    private ReceiverCache receiverCache;

    @Autowired
    private FreemarkerUtils freemarkerUtils;

    public String buildLogAlertConfigErrorJSONString(AlertLogCounter counter, String message) {
        List<Receiver> receiverList = receiverCache.getReceiverConfigs(counter);
        String owner = receiverList.stream().map(Receiver::getOwner).findFirst().orElse("未配置负责人");
        RequestData data = RequestData.builder()
                .onlyCode(getSendCode(counter))
                .mailTitle("log-alert发生配置错误告警")
                .alarmType(counter.getRule().getSendType())
                .mails(receiverList.stream().map(Receiver::getEmail).collect(Collectors.joining(",")))
                .toUser(receiverList.stream().map(Receiver::getCasId).collect(Collectors.joining(",")))
                .msgs(receiverList.stream().map(Receiver::getPrePhone).collect(Collectors.joining(",")))
                .msgContent(LogAlertMessage.buildConfigErrorAlertMessage(counter, owner, message))
                .wechatContent(LogAlertMessage.buildConfigErrorAlertMessage(counter, owner, message))
                .mailContent(LogAlertMessage.buildConfigErrorAlertMessage(counter, owner, message))
                .mailType(DEFAULT_MAIL_TYPE)
                .msgType(DEFAULT_MSG_TYPE)
                .build();
        return decorateAsAlertObject(data);
    }

    public String buildAlertDataJSONString(AlertLogCounter counter) {
        List<Receiver> receiverList = receiverCache.getReceiverConfigs(counter);
        String owner = receiverList.stream().map(Receiver::getOwner).findFirst().orElse("未配置负责人");
        AlertData.RequestData.RequestDataBuilder dataBuilder = RequestData.builder()
                .onlyCode(getSendCode(counter))
                .mailTitle(getMailTitle(counter))
                .alarmType(counter.getRule().getSendType())
                .msgContent(getContent(counter.getRule().getSmsTemplate(), false, counter, owner, AlertMessage.buildMsgAlertMessage(counter, owner)))
                .wechatContent(getContent(counter.getRule().getWechatTemplate(), false, counter, owner, AlertMessage.buildAlertMessage(counter, owner)))
                .mailContent(getContent(counter.getRule().getTemplate(), true, counter, owner, AlertMessage.buildAlertMessage(counter, owner)))
                .mailType(DEFAULT_MAIL_TYPE)
                .msgType(DEFAULT_MSG_TYPE)
                .alarmData(AlertMessage.buildAlertAlarmData(counter, group));

        setReceiverList(counter, receiverList, dataBuilder);
        return decorateAsAlertObject(dataBuilder.build());
    }


    /**
     * 根据模板生成内容
     * @param consumerTemplate 模板
     * @param isMail 如果设置为true，则会替换'\n'为'<br/>'
     * @param alertLogCounter counter对象
     * @param owner 负责人
     * @param defaultMessage 如果没有模板或者模板生成失败，则会返回该消息内容
     * @return 根据模板生成的内容
     */
    private String getContent(String consumerTemplate,
                              boolean isMail,
                              AlertLogCounter alertLogCounter,
                              String owner,
                              String defaultMessage) {
        //如果有模板，使用模板引擎生成
        if (StringUtils.isNotBlank(consumerTemplate)) {
            Optional<String> template = freemarkerUtils.generatorHTML(consumerTemplate,
                    AlertMessage.getTemplateAlertMapParams(alertLogCounter, owner));
            if (template.isPresent()) {
                return template.get();
            }
        }

        //返回默认生成的消息
        return isMail ? defaultMessage.replaceAll("\n", "<br/>") : defaultMessage;
    }

    /**
     * 根据模板生成恢复内容
     * @param consumerTemplate 模板
     * @param isMail 如果设置为true，则会替换'\n'为'<br/>'
     * @param alertLogCounter counter对象
     * @param owner 负责人
     * @param defaultMessage 如果没有模板或者模板生成失败，则会返回该消息内容
     * @return 根据模板生成的内容
     */
    private String getResumeContent(String consumerTemplate,
                                    boolean isMail,
                                    AlertLogCounter alertLogCounter,
                                    String owner,
                                    String defaultMessage) {
        //如果有模板，使用模板引擎生成
        if (StringUtils.isNotBlank(consumerTemplate)) {
            Optional<String> template = freemarkerUtils.generatorHTML(consumerTemplate,
                    AlertMessage.getResumeTemplateAlertMapParams(alertLogCounter, owner));
            if (template.isPresent()) {
                return template.get();
            }
        }

        //返回默认生成的消息
        return isMail ? defaultMessage.replaceAll("\n", "<br/>") : defaultMessage;
    }


    private void setReceiverList(AlertLogCounter counter, List<Receiver> receiverList, RequestData.RequestDataBuilder dataBuilder) {
        String receiver = counter.getAlertLog().getReceiver();
        //日志告警自定义收件人
        if (StringUtils.isNotBlank(receiver)) {
            JSONObject receiverObject = JSONObject.parseObject(receiver);
            if (receiverObject.containsKey(MAILS)) {
                dataBuilder.mails(receiverObject.getJSONArray(MAILS).stream().map(Object::toString).collect(Collectors.joining(",")));
            }

            if (receiverObject.containsKey(CAS_NAMES)) {
                dataBuilder.toUser(receiverObject.getJSONArray(CAS_NAMES).stream().map(Object::toString).collect(Collectors.joining(",")));
            }

            if (receiverObject.containsKey(PHONES)) {
                dataBuilder.msgs(receiverObject.getJSONArray(PHONES).stream().map(phone -> "86" + phone).collect(Collectors.joining(",")));
            }
        } else {
            //使用sre平台配置
            dataBuilder.mails(receiverList.stream().map(Receiver::getEmail).filter(StringUtils::isNotBlank).collect(Collectors.joining(",")))
                    .toUser(receiverList.stream().map(Receiver::getCasId).filter(StringUtils::isNotBlank).collect(Collectors.joining(",")))
                    .msgs(receiverList.stream().map(Receiver::getPrePhone).filter(StringUtils::isNotBlank).collect(Collectors.joining(",")));
        }
    }

    @NotNull
    private String getMailTitle(AlertLogCounter counter) {
        if (StringUtils.isNotBlank(counter.getAlertLog().getSubject())) {
            return counter.getAlertLog().getSubject();
        }
        return counter.getAlertLog().getService() + "发出告警(共" + counter.getAlertTimesInAllCycle() + "条)";
    }

    private String getSendCode(AlertLogCounter counter) {
        String level = getLevelPriorityRule(counter);
        String localLevel = level.toUpperCase();
        switch (localLevel) {
            case WARN:
                return sendCodeWarn;
            case ERROR:
                return sendCodeError;
            case FATAL:
                return sendCodeFatal;
        }
        IllegalArgumentException exception = new IllegalArgumentException("未知level类型");
        LOGGER.error("未知level类型：{}", level, exception);
        throw exception;
    }

    /**
     * 返回对应的level，优先从rule获取；如果rule中level为空，则从log获取
     * @param counter
     * @return
     */
    private String getLevelPriorityRule(AlertLogCounter counter) {
        //优先使用rule配置中的优先级
        if (StringUtils.isNotBlank(counter.getRule().getAlertLevel())) {
            return counter.getRule().getAlertLevel();
        } else {
            return counter.getAlertLog().getLevel();
        }
    }

    public String buildResumeAlertDataJSONString(AlertLogCounter counter) {
        List<Receiver> receiverList = receiverCache.getReceiverConfigs(counter);
        String owner = receiverList.stream().map(Receiver::getOwner).findFirst().orElse("未配置负责人");
        RequestData.RequestDataBuilder dataBuilder = RequestData.builder()
                .onlyCode(getSendCode(counter))
                .mailTitle(getMailTitle(counter))
                .alarmType(counter.getRule().getSendType())
                .msgContent(getResumeContent(counter.getRule().getSmsTemplate(), false, counter, owner, AlertMessage.buildMsgResumeAlertMessage(counter, owner)))
                .wechatContent(getResumeContent(counter.getRule().getWechatTemplate(), false, counter, owner, AlertMessage.buildResumeAlertMessage(counter, owner)))
                .mailContent(getResumeContent(counter.getRule().getTemplate(), true, counter, owner, AlertMessage.buildResumeAlertMessage(counter, owner)))
                .mailType(DEFAULT_MAIL_TYPE)
                .msgType(DEFAULT_MSG_TYPE)
                .alarmData(AlertMessage.buildResumeAlarmData(counter, group));
        setReceiverList(counter, receiverList, dataBuilder);
        return decorateAsAlertObject(dataBuilder.build());
    }

    @NotNull
    private String decorateAsAlertObject(RequestData data) {
        AlertObject alertObject = AlertObject.builder()
                .appName(appName)
                .appSecretKey(appSecretKey)
                .requestData(data)
                .swiftNum(String.valueOf(System.currentTimeMillis()))
                .build();
        return JSONObject.toJSONString(alertObject);
    }

    @Data
    @Builder
    public static class AlertObject  {

        private String appName;

        private String appSecretKey;

        private String swiftNum;

        private RequestData requestData;
    }

    @Data
    @Builder
    private static class RequestData {
        private String onlyCode;
        /**
         * 发送类型
         * 必填（1 邮件和短信，2 邮件，3 短信，4 微信，5 邮件和微信，6 邮件和短信和报警电话，7 短信和报警电话，8 邮件和短信和微信，
         * 9 邮件和短信和微信和报警电话，10 短信和微信，11 短信和微信和报警电话）
         */
        private String alarmType;

        /**
         * 邮件收件人	alarmType为1、2、5、6、8、9时必填，多个逗号分隔
         */
        private String mails;

        /**
         * 短信收件人	alarmType为1、3、6、7、8、9、10、11时必填，需要以86开头，多个逗号分隔
         */
        private String msgs;

        /**
         * 微信收件人	alarmType为4、5、8、9、10、11时填写，多个逗号分隔（例如：qiang.wang,mingming.chen）
         */
        private String toUser;

        /**
         * 发件人;选填，不填默认为1（1 alarm-service@brgroup.com，2 daily_service@brgroup.com，3 dcp@1brgroup.com ，
         * 4 alarm-notify@brgroup.com）
         */
        private String mailType;

        /**
         * 短信运营商	选填，不填默认为1（1 百融通道 2 保筑科技通道 3 语音验证通道 4 零距离365通道）其中：2和3是验证码通道
         */
        private String msgType;

        /**
         * 邮箱
         */
        private String mailTitle;

        /**
         * 短信
         */
        private String msgContent;
        /**
         * 微信
         */
        private String wechatContent;

        /**
         * 邮件内容
         */
        private String mailContent;

        /**
         * 告警处置相关数据
         */
        private AlarmData alarmData;
    }

    @Data
    @Builder
    public static class AlarmData {
        /**
         * 事件ID
         */
        private String eventid;

        /**
         * 值为prometheus/zabbix/application，默认为application
         */
        private String source;

        /**
         * 应用名或集群名
         */
        private String app;

        /**
         * 值为net/hardware/middleware/app
         */
        private String type;

        /**
         * 告警主机
         */
        private String host;

        /**
         * 告警时间 格式为yyyy-mm-dd HH:mm:ss.ms
         */
        private String alarmTime;

        /**
         * 恢复时间 格式为yyyy-mm-dd HH:mm:ss.ms
         */
        private String recoveryTime;

        /**
         * 恢复时间 值为PROMBLEM/OK
         */
        private String msgType;

        /**
         * 告警规则
         */
        private String rule;

        /**
         * 告警规则，规则数组
         */
        private JSONArray alertRuleIdArr;

        /**
         * 告警机房
         */
        private String idc;

        /**
         * 告警信息
         */
        private String message;

        /**
         * 当前值
         */
        private String value;
    }
}
